import { Component, OnInit, OnDestroy } from '@angular/core';

import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';

import { AuthenticationService } from './core/services/authentication.service';
import { BaseDirective } from './core/models/base-directive.model';
import { EncryptionService } from './core/services/encryption.service';
import { TokenService } from './core/services/token.service';
import { WebSocketService } from './core/services/web-socket.service';

// declare const SockJS: any, Stomp: any;

// Register a service in AppComponent providers only if the service must be hidden from components 
// outside the AppComponent tree. They are component-scoped. This is a rare use case.
@Component({
    selector: 'op-app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.scss']
})
export class AppComponent extends BaseDirective implements OnInit, OnDestroy {
    isAuthenticated: boolean;
    isScreenLocked: boolean;
    // private socket: any;
    // private stompClient: any;
    // private subscriptions: any[] = [];

    constructor(
        private authenticationService: AuthenticationService,
        private encryptionService: EncryptionService,
        private tokenService: TokenService,
        private webSocketService: WebSocketService
    ) {
        super();

        // this.subscribeStomp = this.subscribeStomp.bind(this);
    }

    ngOnInit(): void {
        super.ngOnInit();

        this.authenticationService.isAuthenticated$.pipe(takeUntil(this.ngUnsubscribe)).subscribe(p => this.isAuthenticated = p);
        this.authenticationService.isScreenLocked$.pipe(takeUntil(this.ngUnsubscribe)).subscribe(p => this.isScreenLocked = p);

        // this.httpRequestService.getWithoutBaseUrl('foo/hi').subscribe(res => console.dir(res));

        // For WebSocket testing.
        // this.connectWebSocket();
    }

    ngOnDestroy(): void {
        super.ngOnDestroy();

        // this.unsubscribeStomp();
        // this.disconnectWebSocket();
    }

    login(): void {
        // Saves current time which will be used to calculate how many seconds passed till token retrieved from remote server.
        // When calcuates on local we need to consider the time consumed by the remote request.
        let beforeTokenRetrieved = this.commonService.getCurrentDate();

        this.httpRequestService.post('/api/login', {
            username: 'Hui',
            password: '1'
        }).subscribe(res => {
            // Calculates the seconds consumed by remote request.
            let consumedSeconds = (this.commonService.getCurrentDate().getTime() - beforeTokenRetrieved.getTime()) / 1000;

            if (res) {
                this.tokenService.saveToken(Object.assign(res, { request_consumed_seconds: consumedSeconds }))
                this.authenticationService.saveUserInfo(res);
            } else {
                console.error('Failed');
            }
        });
    }

    logout(): void {
        this.httpRequestService.post('/api/logout').subscribe(() => {
            this.tokenService.removeToken();
            this.authenticationService.removeUserInfo();
        });
    }

    getPublic(): void {
        for (let i = 1; i <= 1; i++) {
            this.httpRequestService.get('/product/list').subscribe(res => {
                console.log('request ' + i);
                console.dir(res);
            });
        }
    }

    getRestricted(): void {
        for (let i = 1; i <= 10; i++) {
            this.httpRequestService.get('/order/getProducts').subscribe(res => {
                console.log('request ' + i);
                console.dir(res);
            });
        }
    }

    push(): void {
        // this.httpRequestService.tokenSubject.next('test-token');

        this.webSocketService.connect([
            {
                destination: '/queue/message/user/e01e4962-94ef-4a4a-bd05-726ecbffeb97/20190412044912205',
                handleMessage: (message: any): void => {
                    let messageBody = JSON.parse(message.body);

                    console.log('Incoming message for user2 ...');
                    console.log(messageBody);
                    console.log(messageBody.content);
                }
            }
        ]);
    }

    disconnect(): void {
        this.webSocketService.unsubscribeAll();
        this.webSocketService.disconnect();
    }

    sendMessage(): void {
        // The destination must start with "app" and without server context path.
        this.webSocketService.send('/app/chat', {
            from: 'user1',
            to: 'user2',
            content: 'Hi User2'
        });
    }

    private connectWebSocket(): void {
        // The url must contain server context path.
        this.webSocketService.connect([
            {
                destination: '/queue/message/user/06e6d103-98cf-4e56-a118-1e4222e417b6/20190412042140570',
                handleMessage: (message: any): void => {
                    let messageBody = JSON.parse(message.body);

                    console.log('Incoming message for user1 ...');
                    console.log(messageBody);
                    console.log(messageBody.content);
                }
            },
            // {
            //     destination: '/queue/message/user/e01e4962-94ef-4a4a-bd05-726ecbffeb97/20190412044912205',
            //     handleMessage: (message: any): void => {
            //         let messageBody = JSON.parse(message.body);

            //         console.log('Incoming message for user2 ...');
            //         console.log(messageBody);
            //         console.log(messageBody.content);
            //     }
            // }
        ]);
    }
}